package com.example.demo.sequence;

import java.sql.Timestamp;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

 /** 
 * 描述       :  利用ScheduledExecutorService实现高并发场景下System.curentTimeMillis()的性能问题的优化.
 * @author  87431
 * 版本       :   <版本>
 * 修改时间：      2019年11月16日
 * 修改内容：      <修改内容>
*/
public enum SystemClock {

    /** period:1 代表 1毫秒:（频率：0.001 秒每次）该值不许改动（影响id的生成） */
    INSTANCE(1000);//该值不许改动（影响id的生成）

    /** 时钟频率，该值不许改动（影响id的生成）  */
    private final long period;
    
    private final AtomicLong nowTime;
    private boolean started = false;
    private ScheduledExecutorService executorService;

    static {
    	SystemClock.INSTANCE.initialize();
    }
    
    SystemClock(long period) {
        this.period = period;
        this.nowTime = new AtomicLong(System.currentTimeMillis());
    }
    

    public long getPeriod() {
        return period;
    }

    /**
     * <功能>  定时器初始化
     */
    private void initialize() {
        if (started) {
            return;
        }
        // ScheduledThreadPoolExecutor 入参 1 代表 1个核心线程数。 后面是lambda表达式
        this.executorService = new ScheduledThreadPoolExecutor(1, r -> {
            Thread thread = new Thread(r, "system-clock");
            thread.setDaemon(true);
            return thread;
        });
        // 每period毫秒执行1次赋值操作
        //scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
        executorService.scheduleAtFixedRate(() -> {nowTime.set(System.currentTimeMillis());} ,
                1, this.period, TimeUnit.MILLISECONDS);
        Runtime.getRuntime().addShutdownHook(new Thread(this::destroy));
        started = true;
    }

    /**
     * <功能> 获取毫秒时间 （频率：1 秒每次） 
     * @return
     */
    public long currentTimeMillis() {
        return started ? nowTime.get() : System.currentTimeMillis();
    }
    
    /**
     * <功能> 获取字符串格式的时间：2019-11-16 14:56:07.641
     * @return
     */
    public String currentTime() {
        return new Timestamp(this.currentTimeMillis()).toString();
    }

    /**
     * <功能> 定时任务关闭（获取时间）。
     */
    public void destroy() {
        if (executorService != null) {
            executorService.shutdown();
        }
    }
    
    /**
     * <功能> 定时任务开启（获取时间）。
     */
    public void start() {
        
        if (executorService != null && (executorService.isShutdown()||executorService.isTerminated())) {
            started = false;
        	SystemClock.INSTANCE.initialize();
        }
    }
}